【フロントエンド、バックエンドを一つのリポジトリで管理】monorepoを実現できるNxをさわってみた
どうも!大阪オフィスの西村祐二です。
フロントエンド、バックエンドを一つのリポジトリで管理したいときがあると思います。
それの実現をサポートNxが使い勝手よかったのでご紹介したいと思います。
monorepoとは
1つのリポジトリの中に複数のパッケージを同梱しリポジトリを運用することをmonorepoと言います。
環境構築やビルドなどのプロセスを簡単に統一できることや、 フロントエンド、バックエンドの共通処理の横断した修正が容易などメリットがあります。
特にTypeScriptの場合、型定義ファイルをフロントエンドとバックエンドで共有できて効率よく開発を進めることができるなどのメリットがあります。
ただ、リリースサイクルの違いであったり、規模が大きくなった際の共有処理の管理に問題がでてきたという話もきくので、無作為にmonorepoにするのがいいということではないので、ご注意ください。
Nxとは
Nxはmonorepo用の拡張可能な開発ツールです。
作っているところが、Angular Consoleなどを作っていることもあってAngularフレンドリーなかんじです。
Nxを使用すると、TypeScript、Cypress、Jest、Prettier、Angular、React、Next.js、NestJSを開発ワークフローに追加できます。
Nxはこれらのツールをセットアップし、シームレスに使用できるようにします。
関連ツールとしてはlernaがあります。興味のある方はこちらもウォッチしておくと良さそうです。
試してみる
今回はAngular+NestJSの構成を作ってみます。
環境
- Node.js:v10.15.1
- Angular:8.2.0
- NestJS:6.2.4
- Nx:8.6.0
ワークスペースを作成する
demoというワークスペースを作成します。
$ npx create-nx-workspace@latest demo
すると、どの種類で作成するかきかれるので、今回は「angular-nest」を選択します。
? What to create in the new workspace empty [an empty workspace] web components [a workspace with a single app built using web components] angular [a workspace with a single Angular application] ❯ angular-nest [a workspace with a full stack application (Angular + Nest)] react [a workspace with a single React application] react-express [a workspace with a full stack application (React + Express)] next.js [a workspace with a single Next.js application]
アプリケーションの名前を適当に入力します。ここでは「test」としておきます。また、スタイルシートはデフォルトのCSSにしておきます。
? Application name test ? Default stylesheet format (Use arrow keys) ❯ CSS SASS(.scss) [ http://sass-lang.com ] Stylus(.styl)[ http://stylus-lang.com ] LESS [ http://lesscss.org ]
しばらくすると、作成が完了します。
これだけで、AngularとNestJSの環境の出来上がりです。
APIとアプリケーションをローカル実行してみる
さっそく動かしてみます。
$ cd demo
NestJSのAPIをローカル実行してみます。
ngコマンドで実行できます。
$ ng serve api Starting type checking service... Using 6 workers with 2048MB memory limit Type checking in progress... Hash: ede246eb2fe7b90939e2 Built at: 2019-10-14 14:08:05 Entrypoint main = main.js main.js.map chunk {main} main.js, main.js.map (main) 2.38 KiB [entry] [rendered] Debugger listening on ws://localhost:7777/500ec5fb-5448-44b8-bb24-4eefc50aeaa4 For help, see: https://nodejs.org/en/docs/inspector [Nest] 93931 - 2019-10-14 14:08:06 [NestFactory] Starting Nest application... [Nest] 93931 - 2019-10-14 14:08:06 [InstanceLoader] AppModule dependencies initialized +35ms [Nest] 93931 - 2019-10-14 14:08:06 [RoutesResolver] AppController {/api/}: +14ms [Nest] 93931 - 2019-10-14 14:08:06 [RouterExplorer] Mapped {/hello, GET} route +6ms [Nest] 93931 - 2019-10-14 14:08:06 [NestApplication] Nest application successfully started +26ms Listening at http://localhost:3333/api No type errors found Version: typescript 3.4.5 Time: 2551ms
問題なく動きました!
続いて、Angularのアプリケーションをローカル実行してみます。
別ターミナルで下記コマンドを実行します。
馴染みのあるngコマンドで実行します。
$ ng serve test 10% building 3/3 modules 0 activeℹ 「wds」: Project is running at http://localhost:4200/webpack-dev-server/ ℹ 「wds」: webpack output is served from / ℹ 「wds」: 404s will fallback to //index.html chunk {main} main.js, main.js.map (main) 29.6 kB [initial] [rendered] chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 302 kB [initial] [rendered] chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered] chunk {styles} styles.js, styles.js.map (styles) 10.1 kB [initial] [rendered] chunk {vendor} vendor.js, vendor.js.map (vendor) 3.93 MB [initial] [rendered] Date: 2019-10-14T05:10:04.324Z - Hash: bb4ce34638b05b8e9fdd - Time: 3591ms ** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ ** ℹ 「wdm」: Compiled successfully.
こちらも問題なく実行できました。 ブラウザにアクセスして画面を確認してみると下記のような画面が表示されました。AngularからNestJSのAPIをコールしてメッセージを受け取っていることがわかります。
構成を確認してみる
Nxで作成された構成で特徴的なところをみていきます。構成としては下記のようになっています。
AngularのアプリケーションはテストフレームワークがJest、Cypressに置き換わっているので、ご注意ください。いつも、置き換えている人にとっては手間が省けて嬉しいですね。
api
NestJSのソースが格納されています。
test, test-e2e
Angularのアプリケーションが格納されています。
NestJSと連携できるようにproxy.conf.json
が設定されています。
{ "/api": { "target": "http://localhost:3333", "secure": false } }
api-interfaces
AngularとNestJSで共有で使う型定義ファイルがここに格納されています。
自動的に共有部分が作成されているので手間が省けて嬉しいですね。
export interface Message { message: string; }
nx.json
ここでワークスペースの構成が定義されています。
プロジェクトごとにタグの設定ができ、ビルドする対象やテストする対象をタグを指定して実行できるようです。
{ "npmScope": "demo", "implicitDependencies": { "angular.json": "*", "package.json": "*", "tsconfig.json": "*", "tslint.json": "*", "nx.json": "*" }, "projects": { "test-e2e": { "tags": [] }, "test": { "tags": [] }, "api": { "tags": [] }, "api-interfaces": { "tags": [] } } }
テストを実行してみる
Angularなど触っている方なら馴染みのあるngコマンドでテスト実行できます。
AngularとNestJS両方のテストをコマンドで実行できます。
$ ng test
プロジェクトを指定するとそのプロジェクトのテストのみ実行できます
NestJSのAPIのみテスト実行 $ ng test api Angularのみテスト実行 $ ng test <app-name>
また、AngularのE2EテストはCypressに置き換わっているので、Cypressでテストすることができます。
ng e2e <app-name>-e2e --watch
他にも、Nxでは便利なコマンドがいくつか用意されています。その中に変更したコードに影響があるプロジェクトを検出してテストを実行する、というようなコマンドがあります。
これを使ってテストにかかる時間の短縮などができそうです。
コマンドは下記になります。
$ npm run affected:test
ビルドしてみる
テスト同様、ngコマンドでビルドすることができます。
$ ng build $ ng build api
また、変更したコードに影響があるプロジェクトを検出してビルドを実行する、というようなコマンドがあります。
$ npm run affected:build
依存関係をグラフで表示してみる
1つのリポジトリに収集することによって見通しが悪くなったり、どういった構成になっているかわかりにくくなることが予想されます。その対策のために、Nxでは依存関係をグラフで表示する機能が用意されています。
下記コマンドを実行すると依存関係を表したグラフがブラウザ上に表示されます。
$ npm run dep-graph
さいごに
Nxを使うとコマンド一発で、フロントエンド、バックエンドTypeScriptなAngular+NestJSの構成が作成できます。また、Cypress、Jest構成のテスト環境やビルド環境も揃った状態なので、すぐに開発に取りかかれます。
また、Angularだけじゃなく、React、Next.jsもサポートされています。
Angularを使っている人やバックエンドにNestJSを使っている人、またはフロントエンド、バックエンドをTypeScriptで開発していきたい人にとってはとても重宝するツールなのではないでしょうか。
興味のある方は是非試してみてください。